共计 2666 个字符,预计需要花费 7 分钟才能阅读完成。
《Thinking in Java》第五章中5.7小节“构造器初始化”;
初始化顺序
/**
* @author plm
* @create 2021/2/17 18:18
*/
class House {
private Window w1 = new Window(1);
public House() {
System.out.println("House : ()");
}
private Window w3 = new Window(3);
void fun() {
System.out.println("Have Fun.");
}
private Window w2 = new Window(2);
}
class Window {
public Window(int num) {
System.out.println("Window : (" + num + ")");
}
}
public class OrderOfInitialization {
public static void main(String[] args) {
House house = new House();
house.fun();
}
}
/*
Window : (1)
Window : (3)
Window : (2)
House : ()
Have Fun.
*/
在类的内部,变量定义的先后顺序决定了初始化顺序,即使定义的位置在成员方法和构造器的后面,也会最先得到初始化
Tips:在日常开发过程,我们不建议这么定义,不易维护与阅读。
静态数据的初始化
static
关键字不能应用于局部变量,因此它只能作用于域。
- 一个域是静态的基本类型域,并与也没有进行初始化,那么它就会获得基本类型的标准初始值;
- 一个域是对象引用,name它的默认初始值就是null。
/**
* @author plm
* @create 2021/2/17 18:39
*/
public class StaticInitialization {
public static void main(String[] args) {
System.out.println("Step1.");
new Home();
System.out.println("Step2.");
new Home();
father.fun_1(1);
home.fun_2(2);
}
static Father father = new Father();
static Home home = new Home();
}
class Child {
public Child(int marker) {
System.out.println("Child : (" + marker + ")");
}
void fun(int marker) {
System.out.println("fun : (" + marker + ")");
}
}
class Father {
static Child c1 = new Child(1);
public Father() {
System.out.println("Father()");
c1.fun(1);
}
void fun_1(int marker) {
System.out.println("fun_1 : (" + marker + ")");
}
static Child c2 = new Child(2);
}
class Home {
Child c3 = new Child(3);
static Child c4 = new Child(4);
public Home() {
System.out.println("Home()");
c4.fun(2);
}
void fun_2(int marker) {
System.out.println("fun_2 : (" + marker + ")");
}
static Child c5 = new Child(5);
}
/*
Child : (1)
Child : (2)
Father()
fun : (1)
Child : (4)
Child : (5)
Child : (3)
Home()
fun : (2)
Step1.
Child : (3)
Home()
fun : (2)
Step2.
Child : (3)
Home()
fun : (2)
fun_1 : (1)
fun_2 : (2)
*/
如上代码得出:执行main()
方法(静态方法),必须加载StaticInitialization类,然后其静态域Home和Father被初始化,对应的类就要被加载,由于它们也包含静态域Child,所以Child也会被加载,这个是个特殊场景,所有的类都被static联系起来。
初始化的顺序:静态对象(如果它们尚未因前面的对象创建而未被初始化的话),“非静态”对象。
Tips:
1. 构造器也是静态方法,即使它没有显示的使用static关键字:因此当首次创建类时,或者该类的静态方法及静态域首次被访问时,就会加载该类;
2. 静态初始化只会在该类加载时进行一次
3. 为该类对象开辟内存空间
4. 该类对象的所有基本类型设置为默认值,引用类型设置为null
5. 再进行程序员自己定义的初始化动作:比如给某个字段赋初始值 private String a = "123";
6. 最后执行构造器
显示的静态初始化与非静态实例初始化
前者又称静态代码块,与其他静态初始化动作一样,只在类首次加载,或者首次访问该类的静态数据成员时,仅执行一次;
/**
* @author plm
* @create 2021/2/17 19:28
*/
public class ExplicitStatic {
public static void main(String[] args) {
System.out.println("Start.");
new Cups();
System.out.println("Step2.");
new Cups();
}
}
class Cups {
static Cup c1;
static Cup c2;
Cup c3;
Cup c4;
static {
c1 = new Cup(1);
c2 = new Cup(2);
}
{
c3 = new Cup(3);
c4 = new Cup(4);
}
public Cups() {
System.out.println("Cups init.");
}
}
class Cup {
Cup(int marker) {
System.out.println("Cup : (" + marker + ")");
}
void fun(int marker) {
System.out.println("Fun : (" + marker + ")");
}
}
/*
Start.
Cup : (1)
Cup : (2)
Cup : (3)
Cup : (4)
Cups init.
Step2.
Cup : (3)
Cup : (4)
Cups init.
*/
如上,注意观察非静态实例初始化,仅仅缺少了static
关键字,每次调用构造器,它总是会发生,并且总先于构造方法执行。